package figure8.GUI;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Paint;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleInsets;
import org.jfugue.ChannelPressure;
import org.jfugue.Controller;
import org.jfugue.Instrument;
import org.jfugue.KeySignature;
import org.jfugue.Layer;
import org.jfugue.Measure;
import org.jfugue.MidiParser;
import org.jfugue.Note;
import org.jfugue.ParserListener;
import org.jfugue.Pattern;
import org.jfugue.PitchBend;
import org.jfugue.PolyphonicPressure;
import org.jfugue.Tempo;
import org.jfugue.Time;
import org.jfugue.Voice;
import org.jfugue.extras.GetInstrumentsUsedTool;

import figure8.MIDITrack;

public class MIDIGraph extends JPanel implements ParserListener {
	
	XYSeries series;
	XYSeriesCollection dataSet;
	private static final int EXTERNAL_BUFFER_SIZE = 128000;
	private static int resolution = 50;
	private ArrayList<Integer> notes;
	private ArrayList<Integer> time; 
	private Pattern pattern; 
	
	
	public MIDIGraph(MIDITrack track) {
		this.setLayout(new BorderLayout());
		
		series = new XYSeries("Graph");
		dataSet = new XYSeriesCollection();
		notes = new ArrayList<Integer>();
		time = new ArrayList<Integer>();
		pattern = new Pattern();
		
		JFreeChart chart = ChartFactory.createScatterPlot(null,null,null,dataSet,PlotOrientation.VERTICAL,false,true,false);
		ChartPanel chPanel = new ChartPanel(chart);
		
		chart.setPadding(new RectangleInsets(0, 0, 0, 0));
		
		XYPlot plot = chart.getXYPlot();
		ValueAxis axis = plot.getDomainAxis();
		plot.getRangeAxis().setVisible(false);
		plot.setBackgroundPaint(Color.LIGHT_GRAY);
		plot.getDomainAxis().setVisible(false);
		chart.setBackgroundPaint(Color.WHITE);
		
		this.add(chPanel, BorderLayout.CENTER);
		
		capture(track.getFile());
	}
	
	public void capture(File soundFile){
		
		MidiParser parser = new MidiParser(); 
		parser.addParserListener(this);
		try {
			parser.parse(MidiSystem.getSequence(soundFile));
		} catch (InvalidMidiDataException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		int i = 0;
		while ( i < time.size() && i < notes.size())
		{
			series.add(time.get(i),notes.get(i));
			i++;
		}
		dataSet.addSeries(series);
		
	}

	@Override
	public void channelPressureEvent(ChannelPressure arg0) {
	}

	@Override
	public void controllerEvent(Controller arg0) {
		pattern.add(arg0.getMusicString());
	}

	@Override
	public void instrumentEvent(Instrument arg0) {
		System.err.println("Instrument found");
		pattern.add(arg0.getMusicString());
	}

	@Override
	public void keySignatureEvent(KeySignature arg0) {
		pattern.add(arg0.getMusicString());
	}

	@Override
	public void layerEvent(Layer arg0) {
		pattern.add(arg0.getMusicString());
	}

	@Override
	public void measureEvent(Measure arg0) {
		pattern.add(arg0.getMusicString());
	}

	@Override
	public void noteEvent(Note n) {
		if(n.getDuration() > 0) {
			notes.add((int) n.getValue());
			pattern.addElement(n);
		}	
	}

	@Override
	public void parallelNoteEvent(Note arg0) {
	}

	@Override
	public void pitchBendEvent(PitchBend arg0) {
	}

	@Override
	public void polyphonicPressureEvent(PolyphonicPressure arg0) {
	}

	@Override
	public void sequentialNoteEvent(Note arg0) {
	}

	@Override
	public void tempoEvent(Tempo arg0) {
		pattern.add(arg0.getMusicString());
	}

	@Override
	public void timeEvent(Time t) {
		time.add((int) t.getTime());
		
	}

	@Override
	public void voiceEvent(Voice arg0) {
	}
	
}